package thesis.bean;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.map.OverlaySelectEvent;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;
import org.primefaces.model.map.Polyline;

import thesis.database.Route;
import thesis.database.Service;
import thesis.database.Taxi;
import thesis.javaclass.MapFunction;
import thesis.javaclass.SystemModel;

@ManagedBean(name = "map")
@SessionScoped
public class MapBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private List<Route> routes;
	private Taxi taxi;
	private Service service;
	private Date dateStart;
	private Date dateEnd;
	private MapModel map;
	private String mapCenter = "10.762, 106.685";
	private int zoomLevel = 15;

	public MapBean() {
		map = new DefaultMapModel();
	}

	public Service getService() {
		return service;
	}

	public void setService(Service service) {
		this.service = service;
	}

	public String getMapCenter() {
		return mapCenter;
	}

	public int getZoomLevel() {
		return zoomLevel;
	}

	public void setZoomLevel(int zoomLevel) {
		this.zoomLevel = zoomLevel;
	}

	public MapModel getMap() {
		return map;
	}

	public Date getDateStart() {
		return dateStart;
	}

	public void setDateStart(Date dateStart) {
		this.dateStart = dateStart;
	}

	public Date getDateEnd() {
		return dateEnd;
	}

	public void setDateEnd(Date dateEnd) {
		this.dateEnd = dateEnd;
	}

	public List<Route> getRoutes() {
		return routes;
	}

	public Taxi getTaxi() {
		return taxi;
	}

	public void drawMapOnStart() {
		FacesContext context = FacesContext.getCurrentInstance();
		if (taxi == null)
			return;

		System.out.print(taxi.getTaxiId());

		routes = SystemModel.getRouteIn10Days(taxi.getTaxiId());
		if (routes.size() == 0 || routes == null) {
			context.addMessage(null, new FacesMessage(
					"Found no result in last 10 days", ""));
		} else {
			drawMap();
			context.addMessage(null, new FacesMessage("Found " + routes.size()
					+ " results in last 10 days", ""));
		}
	}

	public void onViewClick() {
		map = new DefaultMapModel();
		FacesContext context = FacesContext.getCurrentInstance();

		if (taxi == null)
			return;

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		String start = format.format(dateStart);
		String end = format.format(dateEnd);

		routes = SystemModel.getRouteById(taxi.getTaxiId(), start, end);

		if (routes.size() == 0 || routes == null) {
			context.addMessage(null, new FacesMessage("Found no result", ""));
			return;
		}

		drawMap();
		context.addMessage(null, new FacesMessage("Found " + routes.size()
				+ " results", ""));
	}

	public void drawMap() {
		ArrayList<LatLng> latlngs = new ArrayList<LatLng>();
		Polyline polyline = new Polyline();

		for (Route r : routes) {
			latlngs.add(new LatLng(Double.parseDouble(r.getLatitude()), Double
					.parseDouble(r.getLongitude())));
		}

		for (LatLng ll : latlngs) {
			map.addOverlay(new Marker(ll, ll.getLat() + "/" + ll.getLng()));
			polyline.getPaths().add(ll);
		}

		mapCenter = routes.get(0).getLatitude() + ", "
				+ routes.get(0).getLongitude();

		polyline.setStrokeWeight(8);
		polyline.setStrokeColor("0000ff");
		polyline.setStrokeOpacity(0.8);
		map.addOverlay(polyline);
		
		if (routes.size() == 1) {
			mapCenter = routes.get(0).getLatitude() + ", "
					+ routes.get(0).getLongitude();
			return;
		}
		
		if (routes.size() > 2) {
			ArrayList<Double> latList = new ArrayList<Double>();
			ArrayList<Double> lngList = new ArrayList<Double>();

			for (Route r : routes) {
				latList.add(Double.parseDouble(r.getLatitude()));
				lngList.add(Double.parseDouble(r.getLongitude()));
			}

			ArrayList<Double> results = MapFunction.getZoomLevel(latList,
					lngList);

			zoomLevel = results.get(0).intValue();
			mapCenter = results.get(1) + ", " + results.get(2);
		}
		System.out.println(zoomLevel);

	}

	public void onMarkerSelect(OverlaySelectEvent event) {
		Marker marker = (Marker) event.getOverlay();
		FacesContext context = FacesContext.getCurrentInstance();
		LatLng ll = marker.getLatlng();
		String temp = "";
		try {
			temp = MapFunction.getLocation(ll.getLat(), ll.getLng());
		} catch (Exception e) {
			e.printStackTrace();
		}

		context.addMessage(null,
				new FacesMessage(temp, ll.getLat() + ", " + ll.getLng()));
	}

	public String view() {
		FacesContext context = FacesContext.getCurrentInstance();
		int id = getIdCode(context);

		System.out.print(id);

		taxi = SystemModel.getTaxi(id);
		map = new DefaultMapModel();

		return ("map-view.jsf?faces-redirect=true");
	}

	public int getIdCode(FacesContext context) {
		Map<String, String> params = context.getExternalContext()
				.getRequestParameterMap();

		return Integer.parseInt(params.get("id"));
	}

}
